package org.webscale.util.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Calendar;

import org.apache.log4j.Logger;


public class FilePreprocessor {
	private static final Logger log = Logger.getLogger(FilePreprocessor.class);
	
	private File sourceFile;
	private File reportFile;
	private File outputFile;
	private File summaryFile;
	private SummaryStats summary;
	private boolean hasHeader = false;
	private String header;

	private int ignoreTopLineCount = 0;
	
	private LineProcessor lineProcessor;
	
	public FilePreprocessor(){
		super();
	}

	public void processFile() throws IOException{
		
		summary.setStartTime(Calendar.getInstance());
		BufferedWriter reportWriter = new BufferedWriter(new FileWriter(reportFile));
		BufferedWriter outputWriter = new BufferedWriter(new FileWriter(outputFile));
		
		 FileInputStream fstream = new FileInputStream(sourceFile);
	     DataInputStream in = new DataInputStream(fstream);
		 BufferedReader br = new BufferedReader(new InputStreamReader(in));
		 String line;
		 
		 // header file;
		 if(this.hasHeader){
			line = getHeader();
			outputWriter.write(line);
			outputWriter.newLine();
		 }
		 
		 boolean eof = false;
		 log.info("Starting to reading the File - " + sourceFile.getAbsolutePath());
		    while (!eof)   {
		    	line = br.readLine();
		    	if(line != null){
		    		processLine(line , reportWriter ,outputWriter );
		    	}else{
		    		eof = true;
		    	}
		    }
		    log.info("Reading Complete File - " + sourceFile.getAbsolutePath());
		    in.close();
		    
		    reportWriter.close();
		    outputWriter.close();
		    summary.setEndTime(Calendar.getInstance());
		    BufferedWriter summaryWriter = new BufferedWriter(new FileWriter(summaryFile));
		    summaryWriter.write(summary.toString());
		    summaryWriter.close();
		    
	}
	
	static int lineCount = 0;
	static int successCount = 0;
	static int failCount = 0;
	static int filterCount = 0;

	private void processLine(String line , BufferedWriter reportWriter , BufferedWriter outputWriter) throws IOException{
		lineCount++;
		log.debug("Line to process .. " + line);
			
		lineProcessor.setLineNumber(lineCount);
		lineProcessor.setSummaryStat(summary);
		lineProcessor.setInput(line);
		// check for validation
		if(lineProcessor.isValidInput()){
			// check for filteration
			if(lineProcessor.isLineFiltered()){
				filterCount ++;
				{
					summary.setFilterCount(filterCount);
					summary.setRowsRead(lineCount);
					summary.setRowsProcessed(successCount);
					summary.setRowsRejected(failCount);
					lineProcessor.updateSummary(summary);
				}
				return;
			}
			String output = lineProcessor.transform();
			outputWriter.write(output);
			outputWriter.newLine();
			successCount++;
		}else{
			ProcessingResult result = lineProcessor.getProcessingResult();
			reportWriter.write(result.getResultMessage() + lineProcessor.getDelimiter() + lineCount);
			reportWriter.newLine();
			failCount++;
		}
		
		summary.setRowsRead(lineCount);
		summary.setRowsProcessed(successCount);
		summary.setRowsRejected(failCount);
		
		lineProcessor.updateSummary(summary);
		
		
	}
	
	public File getSourceFile() {
		return sourceFile;
	}

	public void setSourceFile(File sourceFile) {
		this.sourceFile = sourceFile;
	}

	public File getReportFile() {
		return reportFile;
	}

	public void setReportFile(File reportFile) {
		this.reportFile = reportFile;
	}

	public File getOutputFile() {
		return outputFile;
	}

	public void setOutputFile(File outputFile) {
		this.outputFile = outputFile;
	}

	public int getIgnoreTopLineCount() {
		return ignoreTopLineCount;
	}

	public void setIgnoreTopLineCount(int ignoreTopLineCount) {
		this.ignoreTopLineCount = ignoreTopLineCount;
	}

	public LineProcessor getLineProcessor() {
		return lineProcessor;
	}

	public void setLineProcessor(LineProcessor lineProcessor) {
		this.lineProcessor = lineProcessor;
	}

	public File getSummaryFile() {
		return summaryFile;
	}

	public void setSummaryFile(File summaryFile) {
		this.summaryFile = summaryFile;
	}

	public SummaryStats getSummary() {
		return summary;
	}

	public void setSummary(SummaryStats summary) {
		this.summary = summary;
	}

	public boolean isHasHeader() {
		return hasHeader;
	}

	public void setHasHeader(boolean hasHeader) {
		this.hasHeader = hasHeader;
	}

	public String getHeader() {
		return header;
	}

	public void setHeader(String header) {
		this.header = header;
	}
	
		
}
